const {
    Point
} = require('./point');
const {
    DefaultMusicScoreScale
} = require('../../music-score/js/music-score-const');

const DraggableMouse = {
    props: ['horizontalDragDisabled', 'verticalDragDisabled', 'refInfo', 'point', 'scale'],
    methods: {
        /**
         * 返回true时点击当前组建时不会添加move事件，用来控制指定条件下设置可拖拽（指定条件下禁止拖拽）
         *
         * @default return false
         * @return {BOOL}
         */
        isDragDisabled() {
            return this.dragDisabled;
        },
        editorScale() {
            if (shared && shared.editorManager && shared.editorManager.currentEditor) {
                return shared.editorManager.currentEditor.scale;
            } else {
                return DefaultMusicScoreScale;
            }
        },
        inBody(node) {
            return (node === document.documentElement) || (node === document.body) ? false : document.body.contains(node);
        },
        getDomWhichOutsideBody(tree) {
            let n = tree[0];
            while (n.parentNode !== null) {
                n = n.parentNode;
            }
            let i = tree.indexOf(n);
            return i > -1 ? tree[i + 1] : null;
        },
        dispatchFakeEvent(event, tree) {
            //获取仍在dom树上的最深父节点 , 若节点不存在则直接返回
            const p = this.getDomWhichOutsideBody(tree);
            if (!p) return;

            //创建同名自定义事件
            const E = new CustomEvent(event.type, {
                bubbles: true,
            });

            //拷贝参数
            E.changedTouches = event.changedTouches;
            E.targetTouches = event.targetTouches;

            //触发事件
            p.dispatchEvent(E);
        },
        /**
         * 混入mousedown事件
         * @param event        event对象
         */
        dragMouseDown(event) {
            if (!this.isDragDisabled() && (!this.isSelectable || this.isSelectable())) {
                const t = event.target;
                let n = t;
                const tree = [t];
                while (n.parentNode && n !== document.documentElement) {
                    tree.push(n.parentNode);
                    n = n.parentNode;
                }
                const moveHandle = function (e) {
                    if (!this.inBody(e.target)) {
                        this.dispatchFakeEvent(e, tree);
                    }
                };
                const endHandle = function (e) {
                    if (!this.inBody(e.target)) {
                        this.dispatchFakeEvent(e, tree);
                    }
                    t.removeEventListener('touchmove', this.dragMouseMove);
                    t.removeEventListener('touchend', this.bindMouseUp);
                };
                t.addEventListener('touchmove', this.dragMouseMove);
                t.addEventListener('touchend', this.bindMouseUp);

                let eventPoint = this.getEventPoint(event);
                let _this = this;
                this.originalEventPoint = new Point(eventPoint.x, eventPoint.y);
                this.originalPoint = this.point.clone();
                let eventInfo = {
                    event: event,
                    type: 'mousedown',
                    refInfo: this.$props.refInfo,
                    point: this.point,
                    eventPoint: eventPoint,
                    offset: Point.zero(),
                    originalEventPoint: this.originalEventPoint,
                    originalPoint: this.originalPoint
                };
                this.onDragMouseDown(eventInfo);
                _this.$emit('mouseEvent', eventInfo);
                document.addEventListener('mousemove', _this.bindMouseMove);
                document.addEventListener('mouseup', _this.bindMouseUp);
            }
        },
        /**
         * 混入mousemove事件
         * @param event        event对象
         */
        dragMouseMove(event) {
            // console.log('dragMouseMove:', this.asdasd, event.target);
            // console.log(event);
            let eventPoint = this.getEventPoint(event);
            let offsetX = eventPoint.x - this.originalEventPoint.x;
            let offsetY = eventPoint.y - this.originalEventPoint.y;
            !this.horizontalDragDisabled && (this.point.x = (this.originalPoint.x + offsetX));
            !this.verticalDragDisabled && (this.point.y = (this.originalPoint.y + offsetY));
            let eventInfo = {
                event: event,
                type: 'mousemove',
                refInfo: this.$props.refInfo,
                point: this.point,
                eventPoint: eventPoint,
                offset: new Point(offsetX, offsetY),
                originalEventPoint: this.originalEventPoint,
                originalPoint: this.originalPoint
            };
            this.onDragMouseMove(eventInfo);
            this.$emit('mouseEvent', eventInfo);
            this.$forceUpdate();
        },
        /**
         * 混入mouseup事件
         */
        dragMouseUp(event) {
            let eventPoint = this.getEventPoint(event);
            let offsetX = eventPoint.x - this.originalEventPoint.x;
            let offsetY = eventPoint.y - this.originalEventPoint.y;
            let eventInfo = {
                event: event,
                type: 'mouseup',
                refInfo: this.$props.refInfo,
                point: this.point,
                eventPoint: eventPoint,
                offset: new Point(offsetX, offsetY),
                originalEventPoint: this.originalEventPoint,
                originalPoint: this.originalPoint
            };
            this.$emit('mouseEvent', eventInfo);
            this.onDragMouseUp(eventInfo);
            document.removeEventListener('mousemove', this.bindMouseMove);
            document.removeEventListener('mouseup', this.bindMouseUp);
            event.target.removeEventListener('touchmove', this.dragMouseMove);
            event.target.removeEventListener('touchend', this.bindMouseUp);
        },
        bindMouseMove(event) {
            //绑定mousemove事件
            this.dragMouseMove(event)
        },
        bindMouseUp(event) {
            //绑定mouseup事件
            this.dragMouseUp(event);
        },
        onDragMouseDown(eventInfo) {
        },
        onDragMouseMove(eventInfo) {
        },
        onDragMouseUp(eventInfo) {
        },
        getEventPoint(event) {
            let scale = this.scale || DefaultMusicScoreScale;
            if (event.touches && event.touches.length) {
                return new Point(event.touches[0].pageX * scale / this.editorScale(), event.touches[0].pageY * scale / this.editorScale());
                //return new Point(event.changedTouches[0].pageX * scale / this.editorScale(), event.changedTouches[0].pageY * scale / this.editorScale());
            }
            return new Point(event.pageX * scale / this.editorScale(), event.pageY * scale / this.editorScale());
        },
        onDestroy() {
            // console.log('onDestroy');
            // document.removeEventListener('touchmove', this.dragMouseMove);
            // document.removeEventListener('touchend', this.bindMouseUp);
        }
    },
    destroyed() {
        // this.onDestroy();
    }
};

module.exports = {
    DraggableMouse
};
